iT邦幫忙

2

Leaflet & OpenStreetMap - 整合 Vue.js 製作地圖

Ares 2020-02-23 21:28:078164 瀏覽
  • 分享至 

  • xImage
  •  

我們在上一篇介紹到如何使用 LeafletOpenStreetMap 來製作地圖,不過上一篇是直接使用 CDN 的方式來做載入,而這篇我們會使用安裝的方式,並結合 Vue 來實作,那就開始吧~

安裝

這邊使用 Vue CLI 開啟一個新專案,接著下載 vue2-leaflet 這個套件

$ npm install vue2-leaflet leaflet --save

載入的部分官網寫得相當詳細,我們首先須載入 css,再於全域載入組件,功能依照自己需求做選擇,可參考這裡,這邊順便提一下,如果 icon 無法正常顯示的話,官方這邊也提供了解決方法,我們也直接寫入設定

// main.js

import Vue from "vue";
import App from "./App.vue";

// 載入 vue2-leaflet,依照自己需要載入組件
import { LMap, LTileLayer, LMarker, LPopup, LIcon } from "vue2-leaflet";
// 載入 css
import "leaflet/dist/leaflet.css";

// 啟用載入的各組件
Vue.component("l-map", LMap);
Vue.component("l-tile-layer", LTileLayer);
Vue.component("l-marker", LMarker);
Vue.component("l-popup", LPopup);
Vue.component("l-icon", LIcon);

// 設定預設 icon
import { Icon } from "leaflet";
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
  iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
  iconUrl: require("leaflet/dist/images/marker-icon.png"),
  shadowUrl: require("leaflet/dist/images/marker-shadow.png")
});

Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

創建地圖

為了比較好閱讀,這邊會把資料都在 APP.vue 這個檔案內,基本上就是把之前的功能都用 Vue 寫一次~

<template>
  <div id="app">
    <!-- 初始化地圖設定 -->
    <l-map
      ref="myMap"
      :zoom="zoom"
      :center="center"
      :options="options"
      style="height: 100vh;">
      <!-- 載入圖資 -->
      <l-tile-layer :url="url" :attribution="attribution" />
      
      <!-- 自己所在位置 -->
      <l-marker ref="location" :lat-lng="center">
        <l-popup>
          你的位置
        </l-popup>
      </l-marker>
      <!-- 創建標記點 -->
      <l-marker :lat-lng="item.local" v-for="item in data" :key="item.id">
        <!-- 標記點樣式判斷 -->
        <l-icon
          :icon-url="item.name === '夢時代購物中心'?icon.type.gold:icon.type.black"
          :shadow-url="icon.shadowUrl"
          :icon-size="icon.iconSize"
          :icon-anchor="icon.iconAnchor"
          :popup-anchor="icon.popupAnchor"
          :shadow-size="icon.shadowSize"
        />
        <!-- 彈出視窗 -->
        <l-popup>
          {{ item.name }}
        </l-popup>
      </l-marker>
    </l-map>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      // 模擬資料
      data: [
        { id: 1, name: "夢時代購物中心", local: [22.595153, 120.306923] },
        { id: 2, name: "漢神百貨", local: [22.61942, 120.296386] },
        { id: 3, name: "漢神巨蛋", local: [22.669603, 120.302288] },
        { id: 4, name: "大統百貨", local: [22.630748, 120.318033] }
      ],
      
      zoom: 13,
      center: [22.612961, 120.304167],
      url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
      attribution: `© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors`,
      options: {
        zoomControl: false
      },
      icon: {
        type: {
          black:
            "https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-black.png",
          gold:
            "https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-gold.png"
        },
        shadowUrl:
          "https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png",
        iconSize: [25, 41],
        iconAnchor: [12, 41],
        popupAnchor: [1, -34],
        shadowSize: [41, 41]
      }
    };
  },
  mounted() {
    // 等地圖創建後執行
    this.$nextTick(() => {
      // 獲得目前位置
      navigator.geolocation.getCurrentPosition(position => {
        const p = position.coords;
        // 將中心點設為目前的位置
        this.center = [p.latitude, p.longitude];
        // 將目前的位置的標記點彈跳視窗打開
        this.$refs.location.mapObject.openPopup();
      });
    });
  }
};
</script>

<style>
  html,body {
    padding: 0;
    margin: 0;
  }
</style>

成果如下~
地圖Demo1

plugin

上次介紹 markercluster 這個插件,而他也有 vue2-leaflet-markercluster 這個 Vue 的版本,這次我們一樣把她加入 Demo 中,首先安裝套件

$ npm install vue2-leaflet-markercluster --save

接下來在剛剛的 Demo 中新增幾行程式碼來載入套件

// main.js

// 載入 css
import 'leaflet.markercluster/dist/MarkerCluster.css';
import 'leaflet.markercluster/dist/MarkerCluster.Default.css';
// 載入 markercluster 並啟用
import Vue2LeafletMarkerCluster from 'vue2-leaflet-markercluster';
Vue.component('v-marker-cluster', Vue2LeafletMarkerCluster);

最後再將載入的組件加在頁面上就完成囉

<!-- 加入組件 tag -->
<v-marker-cluster>
  <l-marker :lat-lng="item.local" v-for="item in data" :key="item.id">
    <l-icon
      :icon-url="item.name === '夢時代購物中心' ? icon.type.gold : icon.type.black"
      :shadow-url="icon.shadowUrl"
      :icon-size="icon.iconSize"
      :icon-anchor="icon.iconAnchor"
      :popup-anchor="icon.popupAnchor"
      :shadow-size="icon.shadowSize"
    />
    <l-popup>{{ item.name }}</l-popup>
  </l-marker>
</v-marker-cluster>

成果如下~
地圖Demo2

結語

這次將上一篇的東西全部換成 vue 的組件,基本上只是將 js 內的設定改用 vue 的寫法寫在組件上,功能都是一樣,用法也相當容易,之後就交給大家試試囉!


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言